package com.example.wac.job.config;

import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.lite.spring.api.SpringJobScheduler;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import com.example.wac.job.listener.TaskJobListener;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.Map;

/**
 * @author wuancheng
 * @description
 * @date 2022-05-31 18:18:00
 */
@Configuration
@DependsOn("jobConfig")
public class ElasticJobConfig {
    @Autowired
    ZookeeperRegistryCenter registryCenter;

    @Autowired
    TaskJobListener jobListener;

    @Autowired
    ElasticJobProperties elasticJobProperties;

    @Autowired
    BeanFactory beanFactory;

    /**
     * 反射类的包名
     */
    private final String jobPackage = "com.example.wac.job.";


    /**
     *
     * 服务器加载Servlet -> servlet 构造函数的加载 -> postConstruct->init（init是在service 中的初始化方法. 创建service 时发生的事件.） ->Service->destory->predestory->服务器卸载serlvet
     * 修饰一个非静态的void
     * 如果想在生成时候完成某些初始化操作，而偏偏这些初始化操作又依赖于依赖注入的对象，
     * 此时需要@PostConstruct注解来完成，@PostConstruct 注解的方法将会在依赖注入完成后被自动调用
     * 类初始化调用顺序：构造方法Constructor -> @Autowired -> @PostConstruct
     */
//    @PostConstruct
    public void postConstruct() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Map<String, ElasticJobConfigurationProperties> jobs = elasticJobProperties.getJobs();
        for (Map.Entry<String, ElasticJobConfigurationProperties> entry : jobs.entrySet()) {
            // 通过反射获取的对象类里注入的bean为空
//             SimpleJob job = (SimpleJob) Class.forName(jobPackage + entry.getKey()).newInstance();
            SimpleJob job = (SimpleJob) beanFactory.getBean(Class.forName(jobPackage + entry.getKey()));
            SpringJobScheduler jobScheduler = new SpringJobScheduler(job, registryCenter,
                    getSimpleJobConfiguration(
                            job.getClass(),
                            entry.getValue().getCron(),
                            entry.getValue().getShardingTotalCount(),
                            entry.getValue().getShardingItemParameters()),
                    jobListener
            );
            jobScheduler.init();
        }
    }

    /**
     * 创建简单任务详细信息
     */
    public LiteJobConfiguration getSimpleJobConfiguration(final Class<? extends SimpleJob> jobClass, //任务类
                                                          final String cron,    // 运行周期配置
                                                          final int shardingTotalCount,  //分片个数
                                                          final String shardingItemParameters) {  // 分片参数
        return LiteJobConfiguration.newBuilder(new SimpleJobConfiguration(
                JobCoreConfiguration.newBuilder(jobClass.getName(), cron, shardingTotalCount)
                        .shardingItemParameters(shardingItemParameters)
                        .build(), jobClass.getCanonicalName()))
                .overwrite(true)
                .build();
    }
}
